/*
 * This file is part of the Try! Engine project.
 *
 * Copyright 2010-2011 Emanuele Bertoldi. All rights reserved.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the modified BSD License along with this
 * program. If not, see <http://www.opensource.org/licenses/bsd-license.php>
 */

#include "audiolistener.h"
#include "audiomanager.h"
#include <object.h>

using namespace Try;

PropertyName AudioListener::name = "try.audio.audiolistener";

MessageName AudioListener::Msg::dopplerFactorChanged = "dopplerFactorChanged";
MessageName AudioListener::Msg::dopplerVelocityChanged = "dopplerVelocityChanged";
MessageName AudioListener::Msg::gainChanged = "gainChanged";
MessageName AudioListener::Msg::updated = "updated";

AudioListener::AudioListener(
    Object* owner,
    const Vector3& pos,
    const Vector3& dir,
    const Vector3& vel,
    float gain,
    float doppler_factor,
    float doppler_velocity
    )
    :   Property(AudioListener::name, owner)
{
    this->setPosition(pos);
    this->setDirection(dir);
    this->setVelocity(vel);

    this->setGain(gain);

    this->setDopplerFactor(doppler_factor);
    this->setDopplerVelocity(doppler_velocity);
}

AudioListener::~AudioListener()
{
}

Vector3 AudioListener::position() const
{
    return audio->listenerPosition();
}

Vector3 AudioListener::direction() const
{
    return audio->listenerDirection();
}

Vector3 AudioListener::velocity() const
{
    return audio->listenerVelocity();
}

float AudioListener::gain() const
{
    return audio->listenerGain();
}

float AudioListener::dopplerFactor() const
{
    return audio->dopplerFactor();
}

float AudioListener::dopplerVelocity() const
{
    return audio->dopplerVelocity();
}

bool AudioListener::setDopplerFactor(float factor)
{
    if (audio->setDopplerFactor(factor))
    {
        this->notifyMessage(Message(AudioListener::Msg::dopplerFactorChanged, factor));
        return true;
    }

    return false;
}

bool AudioListener::setDopplerVelocity(float velocity)
{
    if (audio->setDopplerVelocity(velocity))
    {
        this->notifyMessage(Message(AudioListener::Msg::dopplerVelocityChanged, velocity));
        return true;
    }

    return false;
}

bool AudioListener::setGain(float gain)
{
    if (audio->setListenerGain(gain))
    {
        this->notifyMessage(Message(AudioListener::Msg::gainChanged, gain));
        return true;
    }

    return false;
}

bool AudioListener::setPosition(const Vector3& pos)
{
    if (audio->setListenerPosition(pos))
    {
        this->notifyUpdate();
        return true;
    }

    return false;
}

bool AudioListener::setDirection(const Vector3& dir)
{
    if (audio->setListenerDirection(dir))
    {
        this->notifyUpdate();
        return true;
    }

    return false;
}

bool AudioListener::setVelocity(const Vector3& vel)
{
    if (audio->setListenerVelocity(vel))
    {
        this->notifyUpdate();
        return true;
    }

    return false;
}

Property* AudioListener::copy(Object* owner) const
{
    return new AudioListener(
        owner,
        this->position(),
        this->direction(),
        this->velocity(),
        this->gain(),
        this->dopplerFactor(),
        this->dopplerVelocity()
    );
}

void AudioListener::notifyUpdate()
{
    this->notifyMessage(Message(AudioListener::Msg::updated, this->position(), this->direction(), this->velocity()));
}
